﻿namespace UnityEditor
{
    using System;
    using System.Collections.Generic;
    using UnityEditorInternal;
    using UnityEngine;

    internal class ModelImporterClipEditor : AssetImporterInspector
    {
        private const int kFrameColumnWidth = 0x2d;
        private AnimationClipEditor m_AnimationClipEditor;
        private SerializedProperty m_AnimationCompression;
        private SerializedProperty m_AnimationPositionError;
        private SerializedProperty m_AnimationRotationError;
        private SerializedProperty m_AnimationScaleError;
        private SerializedProperty m_AnimationType;
        private SerializedProperty m_AnimationWrapMode;
        private SerializedProperty m_BakeSimulation;
        private SerializedProperty m_ClipAnimations;
        private ReorderableList m_ClipList;
        private SerializedObject m_DefaultClipsSerializedObject;
        private SerializedProperty m_ImportAnimation;
        private SerializedProperty m_LegacyGenerateAnimations;
        public int m_SelectedClipIndexDoNotUseDirectly = -1;
        private static Styles styles;

        private void AddClip(TakeInfo takeInfo)
        {
            this.m_ClipAnimations.InsertArrayElementAtIndex(this.m_ClipAnimations.arraySize);
            AnimationClipInfoProperties animationClipInfoAtIndex = this.GetAnimationClipInfoAtIndex(this.m_ClipAnimations.arraySize - 1);
            animationClipInfoAtIndex.name = this.MakeUniqueClipName(takeInfo.defaultClipName, -1);
            this.SetupTakeNameAndFrames(animationClipInfoAtIndex, takeInfo);
            animationClipInfoAtIndex.wrapMode = 0;
            animationClipInfoAtIndex.loop = false;
            animationClipInfoAtIndex.orientationOffsetY = 0f;
            animationClipInfoAtIndex.level = 0f;
            animationClipInfoAtIndex.cycleOffset = 0f;
            animationClipInfoAtIndex.loopBlend = false;
            animationClipInfoAtIndex.loopBlendOrientation = false;
            animationClipInfoAtIndex.loopBlendPositionY = false;
            animationClipInfoAtIndex.loopBlendPositionXZ = false;
            animationClipInfoAtIndex.keepOriginalOrientation = false;
            animationClipInfoAtIndex.keepOriginalPositionY = true;
            animationClipInfoAtIndex.keepOriginalPositionXZ = false;
            animationClipInfoAtIndex.heightFromFeet = false;
            animationClipInfoAtIndex.mirror = false;
            animationClipInfoAtIndex.keepAdditionalBonesAnimation = true;
            AvatarBodyMask mask = new AvatarBodyMask();
            AvatarSkeletonMask mask2 = new AvatarSkeletonMask();
            animationClipInfoAtIndex.BodyMaskToClip(mask);
            animationClipInfoAtIndex.SkeletonMaskToClip(mask2);
            UnityEngine.Object.DestroyImmediate(mask);
            UnityEngine.Object.DestroyImmediate(mask2);
        }

        private void AddClipInList(ReorderableList list)
        {
            if (this.m_DefaultClipsSerializedObject != null)
            {
                this.TransferDefaultClipsToCustomClips();
            }
            this.AddClip(this.singleImporter.importedTakeInfos[0]);
            this.UpdateList();
            this.SelectClip(list.list.Count - 1);
        }

        private void AnimationClipGUI()
        {
            this.AnimationSettings();
            EditorGUILayout.Space();
            if (base.targets.Length == 1)
            {
                this.AnimationSplitTable();
            }
            else
            {
                GUILayout.Label(styles.clipMultiEditInfo, EditorStyles.helpBox, new GUILayoutOption[0]);
            }
        }

        private void AnimationSettings()
        {
            EditorGUILayout.Space();
            bool flag = true;
            foreach (ModelImporter importer in base.targets)
            {
                if (!importer.isBakeIKSupported)
                {
                    flag = false;
                }
            }
            EditorGUI.BeginDisabledGroup(!flag);
            EditorGUILayout.PropertyField(this.m_BakeSimulation, styles.BakeIK, new GUILayoutOption[0]);
            EditorGUI.EndDisabledGroup();
            if (this.animationType == ModelImporterAnimationType.Legacy)
            {
                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = this.m_AnimationWrapMode.hasMultipleDifferentValues;
                int num2 = (int) ((WrapModeFixed) EditorGUILayout.EnumPopup(styles.AnimWrapModeLabel, (WrapModeFixed) this.m_AnimationWrapMode.intValue, new GUILayoutOption[0]));
                EditorGUI.showMixedValue = false;
                if (EditorGUI.EndChangeCheck())
                {
                    this.m_AnimationWrapMode.intValue = num2;
                }
            }
            EditorGUILayout.Popup(this.m_AnimationCompression, styles.AnimCompressionOpt, styles.AnimCompressionLabel, new GUILayoutOption[0]);
            if (this.m_AnimationCompression.intValue > 0)
            {
                EditorGUILayout.PropertyField(this.m_AnimationRotationError, styles.AnimRotationErrorLabel, new GUILayoutOption[0]);
                EditorGUILayout.PropertyField(this.m_AnimationPositionError, styles.AnimPositionErrorLabel, new GUILayoutOption[0]);
                EditorGUILayout.PropertyField(this.m_AnimationScaleError, styles.AnimScaleErrorLabel, new GUILayoutOption[0]);
                GUILayout.Label(styles.AnimationCompressionHelp, EditorStyles.helpBox, new GUILayoutOption[0]);
            }
        }

        private void AnimationSplitTable()
        {
            if (this.m_ClipList == null)
            {
                this.m_ClipList = new ReorderableList(new List<AnimationClipInfoProperties>(), typeof(string), false, true, true, true);
                this.m_ClipList.onAddCallback = new ReorderableList.AddCallbackDelegate(this.AddClipInList);
                this.m_ClipList.onSelectCallback = new ReorderableList.SelectCallbackDelegate(this.SelectClipInList);
                this.m_ClipList.onRemoveCallback = new ReorderableList.RemoveCallbackDelegate(this.RemoveClipInList);
                this.m_ClipList.drawElementCallback = new ReorderableList.ElementCallbackDelegate(this.DrawClipElement);
                this.m_ClipList.drawHeaderCallback = new ReorderableList.HeaderCallbackDelegate(this.DrawClipHeader);
                this.m_ClipList.elementHeight = 16f;
                this.UpdateList();
                this.m_ClipList.index = this.selectedClipIndex;
            }
            this.m_ClipList.DoList();
            EditorGUI.BeginChangeCheck();
            AnimationClipInfoProperties selectedClipInfo = this.GetSelectedClipInfo();
            if (selectedClipInfo != null)
            {
                if ((this.m_AnimationClipEditor != null) && (this.selectedClipIndex != -1))
                {
                    GUILayout.Space(5f);
                    AnimationClip target = this.m_AnimationClipEditor.target as AnimationClip;
                    if (target.isAnimatorMotion)
                    {
                        this.GetSelectedClipInfo().AssignToPreviewClip(target);
                    }
                    TakeInfo[] importedTakeInfos = this.singleImporter.importedTakeInfos;
                    string[] array = new string[importedTakeInfos.Length];
                    for (int i = 0; i < importedTakeInfos.Length; i++)
                    {
                        array[i] = importedTakeInfos[i].name;
                    }
                    EditorGUI.BeginChangeCheck();
                    string name = selectedClipInfo.name;
                    int index = ArrayUtility.IndexOf<string>(array, selectedClipInfo.takeName);
                    this.m_AnimationClipEditor.takeNames = array;
                    this.m_AnimationClipEditor.takeIndex = ArrayUtility.IndexOf<string>(array, selectedClipInfo.takeName);
                    this.m_AnimationClipEditor.OnHeaderGUI();
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (selectedClipInfo.name != name)
                        {
                            this.TransferDefaultClipsToCustomClips();
                            PatchImportSettingRecycleID.Patch(base.serializedObject, 0x4a, name, selectedClipInfo.name);
                        }
                        int takeIndex = this.m_AnimationClipEditor.takeIndex;
                        if ((takeIndex != -1) && (takeIndex != index))
                        {
                            selectedClipInfo.name = this.MakeUniqueClipName(array[takeIndex], -1);
                            this.SetupTakeNameAndFrames(selectedClipInfo, importedTakeInfos[takeIndex]);
                            GUIUtility.keyboardControl = 0;
                            this.SelectClip(this.selectedClipIndex);
                            target = this.m_AnimationClipEditor.target as AnimationClip;
                        }
                    }
                    this.m_AnimationClipEditor.OnInspectorGUI();
                    if (target.isAnimatorMotion)
                    {
                        this.GetSelectedClipInfo().ExtractFromPreviewClip(target);
                    }
                }
                EditorGUIUtility.LookLikeControls();
                if (EditorGUI.EndChangeCheck())
                {
                    this.TransferDefaultClipsToCustomClips();
                }
            }
        }

        private void DrawClipElement(Rect rect, int index, bool selected, bool focused)
        {
            AnimationClipInfoProperties animationClipInfoAtIndex = this.GetAnimationClipInfoAtIndex(index);
            rect.xMax -= 90f;
            GUI.Label(rect, animationClipInfoAtIndex.name, EditorStyles.label);
            rect.x = rect.xMax;
            rect.width = 45f;
            GUI.Label(rect, animationClipInfoAtIndex.firstFrame.ToString("0.0"), styles.numberStyle);
            rect.x = rect.xMax;
            GUI.Label(rect, animationClipInfoAtIndex.lastFrame.ToString("0.0"), styles.numberStyle);
        }

        private void DrawClipHeader(Rect rect)
        {
            rect.xMax -= 90f;
            GUI.Label(rect, "Clips", EditorStyles.label);
            rect.x = rect.xMax;
            rect.width = 45f;
            GUI.Label(rect, "Start", styles.numberStyle);
            rect.x = rect.xMax;
            GUI.Label(rect, "End", styles.numberStyle);
        }

        private AnimationClipInfoProperties GetAnimationClipInfoAtIndex(int index)
        {
            return new AnimationClipInfoProperties(this.m_ClipAnimations.GetArrayElementAtIndex(index));
        }

        private AnimationClipInfoProperties GetSelectedClipInfo()
        {
            if ((this.selectedClipIndex >= 0) && (this.selectedClipIndex < this.m_ClipAnimations.arraySize))
            {
                return this.GetAnimationClipInfoAtIndex(this.selectedClipIndex);
            }
            return null;
        }

        public override bool HasPreviewGUI()
        {
            return ((this.m_AnimationClipEditor != null) && this.m_AnimationClipEditor.HasPreviewGUI());
        }

        private bool IsDeprecatedMultiAnimationRootImport()
        {
            return ((this.animationType == ModelImporterAnimationType.Legacy) && ((this.legacyGenerateAnimations == ModelImporterGenerateAnimations.InOriginalRoots) || (this.legacyGenerateAnimations == ModelImporterGenerateAnimations.InNodes)));
        }

        private string MakeUniqueClipName(string name, int row)
        {
            int num2;
            string str = name;
            int num = 0;
            do
            {
                num2 = 0;
                for (num2 = 0; num2 < this.m_ClipAnimations.arraySize; num2++)
                {
                    AnimationClipInfoProperties animationClipInfoAtIndex = this.GetAnimationClipInfoAtIndex(num2);
                    if ((str == animationClipInfoAtIndex.name) && (row != num2))
                    {
                        str = name + num.ToString();
                        num++;
                        break;
                    }
                }
            }
            while (num2 != this.m_ClipAnimations.arraySize);
            return str;
        }

        public void OnDestroy()
        {
            UnityEngine.Object.DestroyImmediate(this.m_AnimationClipEditor);
        }

        public void OnEnable()
        {
            this.m_ClipAnimations = base.serializedObject.FindProperty("m_ClipAnimations");
            if (this.m_ClipAnimations.arraySize == 0)
            {
                this.SetupDefaultClips();
            }
            this.ValidateClipSelectionIndex();
            if ((this.m_AnimationClipEditor != null) && (this.selectedClipIndex >= 0))
            {
                this.SyncClipEditor();
            }
            this.m_AnimationType = base.serializedObject.FindProperty("m_AnimationType");
            this.m_LegacyGenerateAnimations = base.serializedObject.FindProperty("m_LegacyGenerateAnimations");
            this.m_ImportAnimation = base.serializedObject.FindProperty("m_ImportAnimation");
            this.m_BakeSimulation = base.serializedObject.FindProperty("m_BakeSimulation");
            this.m_AnimationCompression = base.serializedObject.FindProperty("m_AnimationCompression");
            this.m_AnimationRotationError = base.serializedObject.FindProperty("m_AnimationRotationError");
            this.m_AnimationPositionError = base.serializedObject.FindProperty("m_AnimationPositionError");
            this.m_AnimationScaleError = base.serializedObject.FindProperty("m_AnimationScaleError");
            this.m_AnimationWrapMode = base.serializedObject.FindProperty("m_AnimationWrapMode");
        }

        public override void OnInspectorGUI()
        {
            if (styles == null)
            {
                styles = new Styles();
            }
            EditorGUILayout.PropertyField(this.m_ImportAnimation, new GUILayoutOption[0]);
            if (this.m_ImportAnimation.boolValue && !this.m_ImportAnimation.hasMultipleDifferentValues)
            {
                bool flag = (base.targets.Length == 1) && (this.singleImporter.importedTakeInfos.Length == 0);
                if (this.IsDeprecatedMultiAnimationRootImport())
                {
                    EditorGUILayout.HelpBox("Animation data was imported using a deprecated Generation option in the Rig tab. Please switch to a non-deprecated import mode in the Rig tab to be able to edit the animation import settings.", MessageType.Info);
                }
                else if (flag)
                {
                    if (base.serializedObject.hasModifiedProperties)
                    {
                        EditorGUILayout.HelpBox("The animations settings can be edited after clicking Apply.", MessageType.Info);
                    }
                    else
                    {
                        EditorGUILayout.HelpBox("No animation data available in this model.", MessageType.Info);
                    }
                }
                else if (this.m_AnimationType.hasMultipleDifferentValues)
                {
                    EditorGUILayout.HelpBox("The rigs of the selected models have different animation types.", MessageType.Info);
                }
                else if (this.animationType == ModelImporterAnimationType.None)
                {
                    EditorGUILayout.HelpBox("The rigs is not setup to handle animation. Edit the settings in the Rig tab.", MessageType.Info);
                }
                else if (this.m_ImportAnimation.boolValue && !this.m_ImportAnimation.hasMultipleDifferentValues)
                {
                    this.AnimationClipGUI();
                }
            }
            base.ApplyRevertGUI();
        }

        public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)
        {
            if (this.m_AnimationClipEditor != null)
            {
                this.m_AnimationClipEditor.OnInteractivePreviewGUI(r, background);
            }
        }

        public override void OnPreviewSettings()
        {
            if (this.m_AnimationClipEditor != null)
            {
                this.m_AnimationClipEditor.OnPreviewSettings();
            }
        }

        private void PatchDefaultClipTakeNamesToSplitClipNames()
        {
            foreach (TakeInfo info in this.singleImporter.importedTakeInfos)
            {
                PatchImportSettingRecycleID.Patch(base.serializedObject, 0x4a, info.name, info.defaultClipName);
            }
        }

        private void RemoveClip(int index)
        {
            this.m_ClipAnimations.DeleteArrayElementAtIndex(index);
            if (this.m_ClipAnimations.arraySize == 0)
            {
                this.SetupDefaultClips();
                this.m_ImportAnimation.boolValue = false;
            }
        }

        private void RemoveClipInList(ReorderableList list)
        {
            this.TransferDefaultClipsToCustomClips();
            this.RemoveClip(list.index);
            this.UpdateList();
            this.SelectClip(Mathf.Min(list.index, list.Count - 1));
        }

        internal override void ResetValues()
        {
            base.ResetValues();
            this.m_ClipAnimations = base.serializedObject.FindProperty("m_ClipAnimations");
            this.m_DefaultClipsSerializedObject = null;
            if (this.m_ClipAnimations.arraySize == 0)
            {
                this.SetupDefaultClips();
            }
            this.ValidateClipSelectionIndex();
            this.UpdateList();
            this.SelectClip(this.selectedClipIndex);
        }

        private void SelectClip(int selected)
        {
            UnityEngine.Object.DestroyImmediate(this.m_AnimationClipEditor);
            this.m_AnimationClipEditor = null;
            this.selectedClipIndex = selected;
            if ((this.selectedClipIndex < 0) || (this.selectedClipIndex >= this.m_ClipAnimations.arraySize))
            {
                this.selectedClipIndex = -1;
            }
            else
            {
                AnimationClipInfoProperties animationClipInfoAtIndex = this.GetAnimationClipInfoAtIndex(selected);
                AnimationClip previewAnimationClipForTake = this.singleImporter.GetPreviewAnimationClipForTake(animationClipInfoAtIndex.takeName);
                if (previewAnimationClipForTake != null)
                {
                    this.m_AnimationClipEditor = (AnimationClipEditor) Editor.CreateEditor(previewAnimationClipForTake);
                    this.SyncClipEditor();
                }
            }
        }

        private void SelectClipInList(ReorderableList list)
        {
            this.SelectClip(list.index);
        }

        private void SetupDefaultClips()
        {
            this.m_DefaultClipsSerializedObject = new SerializedObject(base.target);
            this.m_ClipAnimations = this.m_DefaultClipsSerializedObject.FindProperty("m_ClipAnimations");
            this.m_ClipAnimations.arraySize = 0;
            foreach (TakeInfo info in this.singleImporter.importedTakeInfos)
            {
                this.AddClip(info);
            }
        }

        private void SetupTakeNameAndFrames(AnimationClipInfoProperties info, TakeInfo takeInfo)
        {
            info.takeName = takeInfo.name;
            info.firstFrame = (int) Mathf.Round(takeInfo.bakeStartTime * takeInfo.sampleRate);
            info.lastFrame = (int) Mathf.Round(takeInfo.bakeStopTime * takeInfo.sampleRate);
        }

        private void SyncClipEditor()
        {
            if (this.m_AnimationClipEditor != null)
            {
                this.m_AnimationClipEditor.ShowRange(this.GetAnimationClipInfoAtIndex(this.selectedClipIndex));
                this.m_AnimationClipEditor.referenceTransformPaths = this.singleImporter.transformPaths;
            }
        }

        private void TransferDefaultClipsToCustomClips()
        {
            if (this.m_DefaultClipsSerializedObject != null)
            {
                if (base.serializedObject.FindProperty("m_ClipAnimations").arraySize != 0)
                {
                    Debug.LogError("Transferring default clips failed, target already has clips");
                }
                base.serializedObject.CopyFromSerializedProperty(this.m_ClipAnimations);
                this.m_ClipAnimations = base.serializedObject.FindProperty("m_ClipAnimations");
                this.m_DefaultClipsSerializedObject = null;
                this.PatchDefaultClipTakeNamesToSplitClipNames();
                this.SyncClipEditor();
            }
        }

        private void UpdateList()
        {
            if (this.m_ClipList != null)
            {
                List<AnimationClipInfoProperties> list = new List<AnimationClipInfoProperties>();
                for (int i = 0; i < this.m_ClipAnimations.arraySize; i++)
                {
                    list.Add(this.GetAnimationClipInfoAtIndex(i));
                }
                this.m_ClipList.list = list;
            }
        }

        private void ValidateClipSelectionIndex()
        {
            if (this.selectedClipIndex > (this.m_ClipAnimations.arraySize - 1))
            {
                this.selectedClipIndex = -1;
            }
        }

        private ModelImporterAnimationType animationType
        {
            get
            {
                return (ModelImporterAnimationType) this.m_AnimationType.intValue;
            }
            set
            {
                this.m_AnimationType.intValue = (int) value;
            }
        }

        private ModelImporterGenerateAnimations legacyGenerateAnimations
        {
            get
            {
                return (ModelImporterGenerateAnimations) this.m_LegacyGenerateAnimations.intValue;
            }
            set
            {
                this.m_LegacyGenerateAnimations.intValue = (int) value;
            }
        }

        public int selectedClipIndex
        {
            get
            {
                return this.m_SelectedClipIndexDoNotUseDirectly;
            }
            set
            {
                this.m_SelectedClipIndexDoNotUseDirectly = value;
                if (this.m_ClipList != null)
                {
                    this.m_ClipList.index = value;
                }
            }
        }

        private ModelImporter singleImporter
        {
            get
            {
                return (base.targets[0] as ModelImporter);
            }
        }

        private class Styles
        {
            public GUIContent AnimationCompression = EditorGUIUtility.TextContent("ModelImporterAnimCompression");
            public GUIContent AnimationCompressionHelp = EditorGUIUtility.TextContent("ModelImporterAnimComprHelp");
            public GUIContent Animations = EditorGUIUtility.TextContent("ModelImporterAnimations");
            public GUIContent AnimCompressionLabel = EditorGUIUtility.TextContent("ModelImporterAnimComprSetting");
            public GUIContent[] AnimCompressionOpt = new GUIContent[] { EditorGUIUtility.TextContent("ModelImporterAnimComprSettingOff"), EditorGUIUtility.TextContent("ModelImporterAnimComprSettingReduction"), EditorGUIUtility.TextContent("ModelImporterAnimComprSettingReductionAndCompression") };
            public GUIContent AnimPositionErrorLabel = EditorGUIUtility.TextContent("ModelImporterAnimComprPositionError");
            public GUIContent AnimRotationErrorLabel = EditorGUIUtility.TextContent("ModelImporterAnimComprRotationError");
            public GUIContent AnimScaleErrorLabel = EditorGUIUtility.TextContent("ModelImporterAnimComprScaleError");
            public GUIContent AnimWrapModeLabel = new GUIContent("Wrap Mode");
            public GUIContent BakeIK = EditorGUIUtility.TextContent("ModelImporterAnimBakeIK");
            public GUIContent clipMultiEditInfo = new GUIContent("Multi-object editing of clips not supported.");
            public GUIStyle numberStyle = new GUIStyle(EditorStyles.label);
            public GUIContent updateMuscleDefinitionFromSource = new GUIContent("Update", "Update the copy of the muscle definition from the source.");

            public Styles()
            {
                this.numberStyle.alignment = TextAnchor.UpperRight;
            }
        }
    }
}

